package cn.iocoder.yudao.module.of.service.taskapproval;

import cn.iocoder.yudao.framework.common.core.SysConstants;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import cn.iocoder.yudao.module.of.controller.admin.taskapprovalhistory.vo.TaskApprovalHistorySaveReqVO;
import cn.iocoder.yudao.module.of.controller.admin.taskapprovals.vo.TaskApprovalPageReqVO;
import cn.iocoder.yudao.module.of.controller.admin.taskapprovals.vo.TaskApprovalPageResponseVO;
import cn.iocoder.yudao.module.of.controller.admin.taskapprovals.vo.TaskApprovalSaveReqVO;
import cn.iocoder.yudao.module.of.controller.admin.taskhandler.vo.TaskHandlerRespVO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskapprovals.TaskApprovalDO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskhandler.TaskHandlerDO;
import cn.iocoder.yudao.module.of.dal.dataobject.taskinfo.TaskInfoDO;
import cn.iocoder.yudao.module.of.dal.mysql.taskapproval.TaskApprovalMapper;
import cn.iocoder.yudao.module.of.dal.mysql.taskinfo.TaskInfoMapper;
import cn.iocoder.yudao.module.of.enums.ApprovalStatusEnum;
import cn.iocoder.yudao.module.of.enums.TaskLevelEnum;
import cn.iocoder.yudao.module.of.enums.TaskStatusEnum;
import cn.iocoder.yudao.module.of.service.taskapprovalhistory.TaskApprovalHistoryService;
import cn.iocoder.yudao.module.of.service.taskhandler.TaskHandlerService;
import cn.iocoder.yudao.module.of.service.taskinfo.TaskInfoService;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.UserDeptDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.UserDeptMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.of.enums.ErrorCodeConstantsOfTask.TASK_APPROVALS_NOT_EXISTS;
import static cn.iocoder.yudao.module.of.enums.ErrorCodeConstantsOfTask.TASK_APPROVAL_NOT_PERMISSION;

/**
 * 任务审批(下发) Service 实现类
 *
 * @author 超级管理员
 */
@Slf4j
@Service
@Validated
public class TaskApprovalServiceImpl implements TaskApprovalService {

    @Resource
    private TaskApprovalMapper taskApprovalMapper;
    @Resource
    private TaskInfoMapper taskInfoMapper;
    @Resource
    private TaskHandlerService taskHandlerService;
    @Resource
    private UserDeptMapper userDeptMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private DeptService deptService;
    @Resource
    TaskApprovalHistoryService taskApprovalHistoryService;
    @Resource
    private FileMapper fileMapper;


    /**
     * 获得任务审批(下发)分页
     *
     * @param req 分页查询
     * @return 任务审批(下发)分页结果
     */
    public PageResult<TaskApprovalPageResponseVO> getPage(TaskApprovalPageReqVO req) {
        // 对应任务的领导才能审核下发
        boolean ifLdLeader = true; // 是否是集团领导
        List<Long> userIds = null; // 空，则说明时集团领导

        List<UserDeptDO> userDeptDOS = userDeptMapper.selectList(UserDeptDO::getUserId, WebFrameworkUtils.getLoginUserId());
        UserDeptDO JDDept = userDeptDOS.stream().filter(ud -> ud.getDeptId() == SysConstants.JT_LEADER_DEPT.longValue()).findFirst().orElse(null);
        List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(WebFrameworkUtils.getLoginUserId());
        UserRoleDO taskAdminRole = userRoleDOS.stream().filter(ur -> ur.getRoleId().equals(SysConstants.TASK_ADMIN_ROLE_ID)).findFirst().orElse(null);

        if (JDDept == null && taskAdminRole == null) {
            ifLdLeader = false;
            // 非集团领导，则需要获得权限id
            userIds = deptService.getDeptOfUserIds();
        }

        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = taskInfoMapper.getQueryWrapper();
        queryWrapper.distinct();
        queryWrapper.selectAll(TaskInfoDO.class);

        queryWrapper.eq(TaskInfoDO::getTaskLevel, TaskLevelEnum.MASTER_LEVEL.getCode());
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, req.getTaskName());
        queryWrapper.eqIfPresent(TaskInfoDO::getTaskFrom, req.getTaskFrom());
        queryWrapper.eqIfPresent(TaskInfoDO::getTaskType, req.getTaskType());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getDeptId());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getUserName());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getSubDeptId());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getSubUserName());
        queryWrapper.eqIfPresent(TaskApprovalDO::getApprovalStatus, req.getApprovalStatus());
        if (CollectionUtils.isNotEmpty(userIds)) {
            queryWrapper.in(TaskHandlerDO::getCreator, userIds);
        }

        if (CollectionUtils.isNotEmpty(req.getStartTime()) && req.getStartTime().size() == 2) {
            queryWrapper.between(TaskInfoDO::getStartTime, req.getStartTime().get(0), req.getStartTime().get(1));
        }
        if (CollectionUtils.isNotEmpty(req.getEndTime()) && req.getEndTime().size() == 2) {
            queryWrapper.between(TaskInfoDO::getEndTime, req.getEndTime().get(0), req.getEndTime().get(1));
        }

        queryWrapper.leftJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.leftJoin(DeptDO.class, DeptDO::getId, TaskHandlerDO::getDeptId);
        queryWrapper.leftJoin(AdminUserDO.class, AdminUserDO::getId, TaskHandlerDO::getUserId);
        // 右连接，以审核表为准
        queryWrapper.rightJoin(TaskApprovalDO.class, TaskApprovalDO::getTaskId, TaskInfoDO::getId);

        // 处理子任务查询条件
        if (req.getSubTaskDeptId() != null || req.getSubTaskSubDeptId() != null
                || StringUtils.isNotBlank(req.getSubTaskName()) || StringUtils.isNotBlank(req.getSubTaskUserName()) || StringUtils.isNotBlank(req.getSubTaskSubUserName())) {
            List<Long> ids = buildSubTaskQueryWrapper(req, userIds);
            if (CollectionUtils.isNotEmpty(ids)) {
                queryWrapper.in(TaskInfoDO::getId, ids);
            }
        }

        queryWrapper.orderByDesc(TaskInfoDO::getId);

        PageResult<TaskInfoDO> pageResult = taskInfoMapper.selectPage(req, queryWrapper);

        if (pageResult.getTotal() == 0) {
            return PageResult.empty();
        }

        List<TaskApprovalPageResponseVO> taskInfoRespVOS = buildPageResultList(pageResult.getList(), req);

        return new PageResult<>(taskInfoRespVOS, pageResult.getTotal());
    }

    /**
     * 构建分页结果
     *
     * @param masterTaskInfoList 主任务列表
     * @param req                查询条件
     */
    private List<TaskApprovalPageResponseVO> buildPageResultList(List<TaskInfoDO> masterTaskInfoList, TaskApprovalPageReqVO req) {
        List<TaskApprovalPageResponseVO> list = new ArrayList<>();

        masterTaskInfoList.forEach(task -> {
            // 主任务
            TaskApprovalPageResponseVO vo = buildTaskDetailVO(task);

            // 子任务
            List<TaskInfoDO> subTaskList = buildSubTaskQueryWrapperOfResult(task.getId(), req);
            List<TaskApprovalPageResponseVO> subTask = subTaskList.stream().map(this::buildTaskDetailVO).collect(Collectors.toList());

            vo.setChildren(subTask);

            list.add(vo);
        });

        return list;
    }

    /**
     * 构造子任务的查询条件
     *
     * @param req 查询条件
     */
    private List<Long> buildSubTaskQueryWrapper(TaskApprovalPageReqVO req, List<Long> userIds) {
        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = taskInfoMapper.getQueryWrapper();
        queryWrapper.distinct();
        queryWrapper.select(TaskInfoDO::getParentId);
        // 如果子查询条件是空，则不查询，只默认查询主任务
        queryWrapper.eq(TaskInfoDO::getTaskLevel, TaskLevelEnum.SUB_LEVEL.getCode());
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, req.getSubTaskName());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getSubTaskDeptId());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getSubTaskSubDeptId());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getSubTaskUserName());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getSubTaskSubUserName());
        queryWrapper.eqIfPresent(TaskApprovalDO::getApprovalStatus, req.getApprovalStatus());

        queryWrapper.leftJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.leftJoin(DeptDO.class, DeptDO::getId, TaskHandlerDO::getDeptId);
        queryWrapper.leftJoin(AdminUserDO.class, AdminUserDO::getId, TaskHandlerDO::getUserId);
        queryWrapper.leftJoin(TaskApprovalDO.class, TaskApprovalDO::getTaskId, TaskInfoDO::getId);
        if (CollectionUtils.isNotEmpty(userIds)) {
            queryWrapper.in(TaskHandlerDO::getCreator, userIds);
        }

        return taskInfoMapper.selectList(queryWrapper).stream().map(TaskInfoDO::getParentId).collect(Collectors.toList());
    }

    /**
     * 获得子任务详情
     *
     * @param masterTaskId
     * @param req
     * @return
     */
    private List<TaskInfoDO> buildSubTaskQueryWrapperOfResult(Long masterTaskId, TaskApprovalPageReqVO req) {
        MPJLambdaWrapperX<TaskInfoDO> queryWrapper = taskInfoMapper.getQueryWrapper();
        queryWrapper.distinct();
        queryWrapper.selectAll(TaskInfoDO.class);
        // 如果子查询条件是空，则不查询，只默认查询主任务
        queryWrapper.eq(TaskInfoDO::getParentId, masterTaskId);
        queryWrapper.eq(TaskInfoDO::getTaskLevel, TaskLevelEnum.SUB_LEVEL.getCode());
        queryWrapper.likeIfPresent(TaskInfoDO::getTaskName, req.getSubTaskName());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getSubTaskDeptId());
        queryWrapper.eqIfPresent(TaskHandlerDO::getDeptId, req.getSubTaskSubDeptId());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getSubTaskUserName());
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, req.getSubTaskSubUserName());
        queryWrapper.eqIfPresent(TaskApprovalDO::getApprovalStatus, req.getApprovalStatus());

        queryWrapper.leftJoin(TaskHandlerDO.class, TaskHandlerDO::getTaskId, TaskInfoDO::getId);
        queryWrapper.leftJoin(DeptDO.class, DeptDO::getId, TaskHandlerDO::getDeptId);
        queryWrapper.leftJoin(AdminUserDO.class, AdminUserDO::getId, TaskHandlerDO::getUserId);
        queryWrapper.leftJoin(TaskApprovalDO.class, TaskApprovalDO::getTaskId, TaskInfoDO::getId);

        return taskInfoMapper.selectList(queryWrapper);
    }


    /**
     * 构造任务详情
     * 含审批信息
     *
     * @param task 任务id
     * @return 结果
     */
    private TaskApprovalPageResponseVO buildTaskDetailVO(TaskInfoDO task) {
        TaskApprovalPageResponseVO vo = new TaskApprovalPageResponseVO();
        BeanUtils.copyProperties(task, vo);
        vo.setStatusName(TaskStatusEnum.valueOf(vo.getStatus(), task.getTaskLevel()));

        List<TaskHandlerRespVO> taskHandler = taskHandlerService.getTaskHandler(task.getId());
        vo.setTaskHandlerList(taskHandler);

        if (CollectionUtils.isNotEmpty(task.getTaskAttachment())) {
            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, task.getTaskAttachment());
            vo.setTaskAttachmentList(fileDOS);
        }
        if (CollectionUtils.isNotEmpty(task.getTaskDocFile())) {
            List<FileDO> fileDOS = fileMapper.selectList(FileDO::getId, task.getTaskDocFile());
            vo.setTaskDocFileList(fileDOS);
        }

        // 补充审批信息
        LambdaQueryWrapper<TaskApprovalDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TaskApprovalDO::getTaskId, task.getId());
        TaskApprovalDO taskApprovalDO = taskApprovalMapper.selectOne(queryWrapper);
        if (taskApprovalDO != null) {
            vo.setTaskId(task.getId());
            vo.setApprovalOpinion(taskApprovalDO.getApprovalOpinion());
            vo.setApprovalStatus(taskApprovalDO.getApprovalStatus());
            vo.setApprovalTime(taskApprovalDO.getApprovalTime());
        }
        return vo;
    }

    /**
     * 登记后提交审核
     * <p>
     * 所有任务提交审批
     *
     * @param taskInfoList 任务信息
     */
    @Override
    public void createTaskApproval(List<TaskInfoDO> taskInfoList) {

        taskInfoList.forEach(task -> {
            TaskApprovalDO approvalDO = BeanUtils.toBean(task, TaskApprovalDO.class);
            approvalDO.setId(null);
            approvalDO.setTaskId(task.getId());
            approvalDO.setApprovalStatus(ApprovalStatusEnum.PENDING.getStatus());

            LambdaQueryWrapper<TaskApprovalDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TaskApprovalDO::getTaskId, task.getId());
            Long count = taskApprovalMapper.selectCount(queryWrapper);
            if (count < 1) {
                taskApprovalMapper.insert(approvalDO);
            }
        });

    }

    /**
     * 任务审批
     *
     * @param updateReqVO 审批信息
     */
    @Transactional
    @Override
    public void taskApproval(TaskApprovalSaveReqVO updateReqVO) {
        // 校验存在
        validateTaskApprovalsExists(updateReqVO.getTaskId());
        Long userId = WebFrameworkUtils.getLoginUserId(); // 高任翔的领导为149(黄占春)
        // 校验当前用户是否有审批权限
        TaskInfoDO taskInfo = taskInfoMapper.selectById(updateReqVO.getTaskId());

        List<TaskHandlerRespVO> taskMainHandler = taskHandlerService.getTaskMainHandler(taskInfo.getId());

        // 创建人领导下发【或者使用办理人的user】
        Long leaderId = deptService.getLeaderId(taskMainHandler.get(0).getDeptId());
        if (!Objects.equals(leaderId, userId)) {
            log.error("用户无权审核, 用户id={}, 任务id={}", userId, updateReqVO.getTaskId());
            throw exception(TASK_APPROVAL_NOT_PERMISSION);
        }

        List<TaskInfoDO> taskInfoList = taskInfoService.listTaskListByMasterId(updateReqVO.getTaskId());

        // 判断是否在审核记录表中，没有先添加
        LambdaQueryWrapper<TaskApprovalDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TaskApprovalDO::getTaskId, updateReqVO.getTaskId());
        if (taskApprovalMapper.selectOne(queryWrapper) == null) {
            List<TaskApprovalDO> list = taskInfoList.stream().map(task -> {
                TaskApprovalDO approvalDO = BeanUtils.toBean(task, TaskApprovalDO.class);
                approvalDO.setId(null);
                approvalDO.setTaskId(task.getId());
                approvalDO.setApprovalStatus(ApprovalStatusEnum.PENDING.getStatus());
                return approvalDO;
            }).collect(Collectors.toList());
            taskApprovalMapper.insertBatch(list);
        }

        taskInfoList.forEach(taskInfoDO -> {
            Long taskId = taskInfoDO.getId();
            // 更新
            TaskApprovalDO updateObj = new TaskApprovalDO();
            updateObj.setApprovalStatus(updateReqVO.getApprovalStatus());
            updateObj.setApprovalUserId(userId);
            updateObj.setApprovalOpinion(updateReqVO.getApprovalOpinion());
            updateObj.setApprovalTime(LocalDateTime.now());

            LambdaQueryWrapper<TaskApprovalDO> updateWrapper = new LambdaQueryWrapper<>();
            updateWrapper.eq(TaskApprovalDO::getTaskId, taskId);
            taskApprovalMapper.update(updateObj, updateWrapper);

            // 添加到历史记录表
            TaskApprovalHistorySaveReqVO historyReqVO = BeanUtils.toBean(updateReqVO, TaskApprovalHistorySaveReqVO.class);
            historyReqVO.setTaskId(taskId);
            taskApprovalHistoryService.createTaskApprovalHistory(historyReqVO);

        });

        // 更新任务状态
        taskInfoMapper.updateStatus(updateReqVO.getTaskId(), TaskStatusEnum.PASS, true);
    }

    /**
     * 校验任务审批(下发)是否存在
     *
     * @param id 主键
     */
    private void validateTaskApprovalsExists(Long id) {
        LambdaQueryWrapper<TaskApprovalDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TaskApprovalDO::getTaskId, id);
        if (taskApprovalMapper.selectCount(queryWrapper) < 1) {
            throw exception(TASK_APPROVALS_NOT_EXISTS);
        }
    }


}